home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 07 - 1991 / 07.12 Dec 91 / Transfer Menu Code / Transfer.p < prev    next >
Encoding:
Text File  |  1988-12-28  |  21.2 KB  |  935 lines  |  [TEXT/MPS ]

  1. (*******************************************************************
  2.     
  3.     Transfer.p
  4.     
  5.     Demo of a dynamic Transfer menu.
  6.     
  7.     (c) 1988, by Clifford Story & Attic Software
  8.     
  9. *******************************************************************)
  10.  
  11. program Transfer;
  12.     
  13. (******************************************************************)
  14.     
  15.     uses memtypes, quickdraw, osintf, toolintf, packintf, Common;
  16.     
  17. (*******************************************************************
  18.     
  19.     Program constants:
  20.         
  21. *******************************************************************)
  22.  
  23.     const
  24.  
  25.         applenum                =    1001;
  26.             aboutitem        =    1;
  27.             atticitem        =    2;
  28.  
  29.         filenum                =    1002;
  30.             quititem            =    1;
  31.  
  32.         editnum                =    1003;
  33.             undoitem            =    1;
  34.             cutitem            =    3;
  35.             copyitem            =    4;
  36.             pasteitem        =    5;
  37.             clearitem        =    6;
  38.  
  39.         transnum                =    1004;
  40.             transitem        =    1;
  41.             edititem            =    2;
  42.         
  43.         messagedialog        =    1001;
  44.         editdialog            =    1002;
  45.             editlist            =    4;
  46.             editdelete        =    5;
  47.             editline            =    6;
  48.         
  49. (*******************************************************************
  50.     
  51.     Program variables:
  52.         
  53. *******************************************************************)
  54.         
  55.     var
  56.     
  57.         APPLEMENU            :    MenuHandle;
  58.         FILEMENU                :    MenuHandle;
  59.         EDITMENU             :    MenuHandle;
  60.         TRANSMENU             :    MenuHandle;
  61.         
  62.         DONE                    :    logical;
  63.         JEVENT                :    logical;
  64.         
  65.         HARDDISK                :    logical;
  66.         DEFVOL                :    integer;
  67.         MENUHEIGHT            :    integer;
  68.         
  69.         MAINEVENT            :    EventRecord;
  70.         
  71. (******************************************************************)
  72.     
  73.     procedure _datainit; external;
  74.     
  75. (******************************************************************)
  76.     
  77.     {$R-}
  78.     {$SC+}
  79.     
  80. (******************************************************************)
  81.     
  82.     procedure panic;
  83.     
  84.         begin
  85.  
  86.             ExitToShell;
  87.  
  88.         end;
  89.         
  90. (******************************************************************)
  91.         
  92.     procedure centerdialog(thetype : OSType; theid : integer);
  93.         
  94.         var
  95.             thehandle        :    AlertTHndl;
  96.         
  97.         begin
  98.             
  99.             thehandle := AlertTHndl(GetResource(thetype, theid));
  100.             HLock(Handle(thehandle));
  101.             with thehandle^^ do begin
  102.                 
  103.                 with boundsRect do
  104.                     SetRect(boundsRect, 0, 0, right - left, bottom - top);
  105.                 
  106.                 with screenBits.bounds, boundsRect.botright do
  107.                     OffsetRect(boundsRect, (right - left - h) div 2,
  108.                                     (bottom - top - v + 2 * MENUHEIGHT) div 3);
  109.             
  110.             end;
  111.             HUnlock(Handle(thehandle));
  112.         
  113.         end;
  114.     
  115. (******************************************************************)
  116.     
  117.     procedure message(what : Str255);
  118.         
  119.         var
  120.             dummy                :    integer;
  121.         
  122.         begin
  123.             
  124.             InitCursor;
  125.             ParamText(what, '', '', '');
  126.             centerdialog('ALRT', messagedialog);
  127.             dummy := Alert(messagedialog, nil);
  128.         
  129.         end;
  130.         
  131. (******************************************************************)
  132.     
  133.     procedure initmac;
  134.     
  135.         begin
  136.  
  137.             MaxApplZone;
  138.             InitGraf(@thePort);
  139.             InitFonts;
  140.             InitWindows;
  141.             InitCursor;
  142.             InitMenus;
  143.             TEInit;
  144.             InitDialogs(@panic);
  145.             
  146.             UnloadSeg(@_datainit);
  147.             
  148.         end;
  149.         
  150. (******************************************************************)
  151.             
  152.     procedure setupmenus;
  153.             
  154.         begin
  155.         
  156.             APPLEMENU := GetMenu(applenum);
  157.             AddResMenu(APPLEMENU, 'DRVR');
  158.             InsertMenu(APPLEMENU, 0);
  159.             
  160.             FILEMENU := GetMenu(filenum);
  161.             InsertMenu(FILEMENU, 0);
  162.             
  163.             EDITMENU := GetMenu(editnum);
  164.             InsertMenu(EDITMENU, 0);
  165.             
  166.             TRANSMENU := GetMenu(transnum);
  167.             InsertMenu(TRANSMENU, 0);
  168.             
  169.             DrawMenuBar;
  170.             
  171.         end;
  172.         
  173. (*******************************************************************
  174.     
  175.     initglobals
  176.     -----------
  177.     
  178.     This routine runs before anything might change the default volume,
  179.     so the GetVol call will return the volume reference number of
  180.     the volume the Transfer application is launched from.
  181.     
  182. *******************************************************************)
  183.     
  184.     procedure initglobals;
  185.     
  186.         var
  187.             index                :    integer;
  188.     
  189.         begin
  190.  
  191.             for index := 1 to 10 do
  192.                 MoreMasters;
  193.             
  194.             if BitTst(Ptr(rom85), 0) then begin
  195.                 MENUHEIGHT := 20;
  196.                 JEVENT := false;
  197.             end else begin
  198.                 MENUHEIGHT := shortpointer(mbarheight)^;
  199.                 JEVENT := (NGetTrapAddress($A860, ToolTrap)
  200.                                 <> NGetTrapAddress($A89F, ToolTrap));
  201.             end;
  202.             
  203.             if GetVol(nil, DEFVOL) <> noErr then
  204.                 DEFVOL := 0;
  205.             
  206.             DONE := false;
  207.             
  208.         end;
  209.  
  210. (******************************************************************)
  211.     
  212.     procedure clickapplemenu(theitem : integer);
  213.     
  214.         var
  215.             itemname            :    Str255;
  216.             savedport        :    GrafPtr;
  217.             dummy                :    integer;
  218.             newport            :    GrafPort;
  219.             thepicture        :    PicHandle;
  220.             therect            :    Rect;
  221.  
  222.         begin
  223.         
  224.             if theitem > 3 then begin
  225.                 GetItem(APPLEMENU, theitem, itemname);
  226.                 GetPort(savedport);
  227.                 dummy := OpenDeskAcc(itemname);
  228.                 SetPort(savedport);
  229.             end else if theitem < 3 then begin
  230.                 
  231.                 InitCursor;
  232.                 GetPort(savedport);
  233.                 OpenPort(@newport);
  234.                 SetPort(@newport);
  235.                 
  236.                 thepicture := PicHandle(GetResource('PICT',
  237.                                 1000 + theitem));
  238.                 with thepicture^^.picFrame do
  239.                     SetRect(therect, 0, 0, right - left, bottom - top);
  240.                 with screenBits.bounds, therect.botright do
  241.                     OffsetRect(therect, (right - left - h) div 2,
  242.                                     (bottom - top - v) div 3);
  243.                 DrawPicture(thepicture, therect);
  244.                 
  245.                 repeat until Button;
  246.                 
  247.                 ClosePort(@newport);
  248.                 DrawMenuBar;
  249.                 PaintBehind(WindowPeek(FrontWindow),
  250.                                 RgnHandle(longpointer(grayrgn)^));
  251.                 
  252.                 SetPort(savedport);
  253.                 FlushEvents(everyEvent, 0);
  254.             
  255.             end;
  256.  
  257.         end;
  258.         
  259. (*******************************************************************
  260.     
  261.     doquit
  262.     ------
  263.     
  264.     This routine closes all desk accessory windows before a quit or
  265.     transfer.  DONE should remain false in event of a transfer, so
  266.     the program can continue if the transfer fails.
  267.     
  268. *******************************************************************)
  269.     
  270.     procedure doquit(quitting : logical);
  271.         
  272.         var
  273.             thewindow        :    windowpeek;
  274.         
  275.         begin
  276.             
  277.             thewindow := windowpeek(frontwindow);
  278.             
  279.             while thewindow <> nil do
  280.                 with thewindow^ do begin
  281.                     if windowkind < 0 then
  282.                         closedeskacc(windowkind);
  283.                     thewindow := nextwindow;
  284.                 end;
  285.             
  286.             if quitting then
  287.                 DONE := true;
  288.             
  289.         end;
  290.         
  291. (*******************************************************************
  292.     
  293.     launch
  294.     ------
  295.     
  296.     The Segment Loader's _launch trap is register-based; it expects
  297.     A0 to contain a pointer to a launch record.  This glue routine
  298.     builds the record on the stack, moves the stack pointer to A0,
  299.     then calls the trap.
  300.     
  301. *******************************************************************)
  302.     
  303.     procedure launch(config : integer; name : Ptr); inline $204F, $A9F2;
  304.     
  305.     {    movea.l        A7,A0
  306.         _launch                    }
  307.     
  308. (*******************************************************************
  309.     
  310.     transferappl
  311.     ------------
  312.     
  313.     This routine launches the application “name”, from the directory
  314.     and volume specified.
  315.     
  316.     First, it tells _launch where to look.  If the program is running
  317.     under MFS, this is simply the volume (no real folders).  Under
  318.     HFS, it opens a working directory and sets the volume to that.
  319.     
  320.     Next, it makes sure the application is there, with a call to
  321.     GetFInfo (first converting the str31 to an Str255 first, to
  322.     satisfy Pascal's type rules).  If it is, then it launchs it.
  323.     
  324.     If the application gets launched successfully, then this program
  325.     is finished.  If it is still running, then something must have
  326.     gone wrong.
  327.     
  328. *******************************************************************)
  329.  
  330.     procedure transferappl(name : str31;
  331.                     volume : integer; directory : long);
  332.         
  333.         const
  334.             procID            =    $54524E53;
  335.         
  336.         var
  337.             thestring        :    Str255;
  338.             anerror            :    integer;
  339.             theblock            :    WDPBRec;
  340.             theinfo            :    FInfo;
  341.         
  342.         begin
  343.             
  344.             BlockMove(@name, @thestring, 32);
  345.             
  346.             if shortpointer(fsfcblen)^ = -1 then
  347.                 anerror := SetVol(nil, volume)
  348.             else with theblock do begin
  349.                 
  350.                 ioCompletion := nil;
  351.                 ioNamePtr := nil;
  352.                 ioVRefNum := volume;
  353.                 ioWDProcID := procID;
  354.                 ioWDDirID := directory;
  355.                 anerror := PBOpenWD(@theblock, false);
  356.                 
  357.                 if anerror = noErr then
  358.                     anerror := SetVol(nil, ioVRefNum)
  359.                 
  360.             end;
  361.             
  362.             if anerror = noErr then begin
  363.                 anerror := GetFInfo(thestring, 0, theinfo);
  364.                 if (anerror = noErr) and (theinfo.fdType = 'APPL') then begin
  365.                     doquit(false);
  366.                     launch(0, @thestring);
  367.                 end;
  368.             end;
  369.             
  370.             message(concat('Sorry!  Couldn''t find “', thestring, '”.'));
  371.         
  372.         end;
  373.     
  374. (*******************************************************************
  375.     
  376.     diskfilter
  377.     ----------
  378.     
  379.     This is a hack to spot removeable volumes.  If the volume is
  380.     removeable, the the “Eject” button is active; otherwise, the
  381.     button is dimmed.  So look at the button to determine the type
  382.     of the volume.
  383.     
  384. *******************************************************************)
  385.  
  386.     function diskfilter(theitem : integer;
  387.                     thedialog : DialogPtr) : integer;
  388.         
  389.         var
  390.             thetype            :    integer;
  391.             thehandle        :    Handle;
  392.             therect            :    Rect;
  393.             
  394.         begin
  395.             
  396.             if theitem = getOpen then begin
  397.                 GetDItem(thedialog, getEject, thetype, thehandle, therect);
  398.                 HARDDISK := ControlHandle(thehandle)^^.contrlhilite = 255;
  399.             end;
  400.             
  401.             diskfilter := theitem;
  402.             
  403.         end;
  404.     
  405. (*******************************************************************
  406.     
  407.     newtransfer
  408.     -----------
  409.     
  410.     This routine puts up an SFGetFile dialog and transfers to the
  411.     chosen application.  It gets the application's volume and
  412.     directory from low-memory globals, and the name from the SFReply
  413.     record, then calls the “transferappl” routine above.
  414.     
  415.     In between, it may record the application on the Transfer menu
  416.     (to be displayed the next time the program is run).  It will do
  417.     this if either the application's volume is not removeable, or if
  418.     the application is on the same volume as this program.  The idea
  419.     is that the target application should not be separated from the
  420.     program if it's to be added to the Transfer menu.
  421.     
  422.     The actual addition is a little bit tricky, since the menu should
  423.     be in alphabetical order.
  424.     
  425. *******************************************************************)
  426.  
  427.     procedure newtransfer;
  428.         
  429.         var
  430.             thepoint            :    Point;
  431.             thelist            :    SFTypeList;
  432.             thereply            :    SFReply;
  433.             newappl            :    tline;
  434.             thehandle        :    thandle;
  435.             thecount            :    integer;
  436.             index                :    integer;
  437.             
  438.         begin
  439.             
  440.             with screenBits.bounds do
  441.                 SetPt(thepoint, (right - left - 348) div 2,
  442.                                 (bottom - top - 200
  443.                                 + 2 * MENUHEIGHT) div 3);
  444.             thelist[0] := 'APPL';
  445.             
  446.             SFGetFile(thepoint, '', nil, 1, thelist, @diskfilter, thereply);
  447.             
  448.             if thereply.good then begin
  449.                 
  450.                 with newappl do begin
  451.                     volume := - shortpointer(sfsavedisk)^;
  452.                     directory := longpointer(curdirstore)^;
  453.                     BlockMove(@thereply.fname, @name, 32);
  454.                 end;
  455.                 
  456.                 if HARDDISK or (newappl.volume = DEFVOL) then begin
  457.                     
  458.                     thehandle := thandle(GetResource('TRNS', 1001));
  459.                     thecount := thehandle^^.count + 1;
  460.                     thehandle^^.count := thecount;
  461.                     SetHandleSize(Handle(thehandle),
  462.                                     2 + thecount * sizeof(tline));
  463.                     
  464.                     HLock(Handle(thehandle));
  465.                     with thehandle^^ do begin
  466.                         
  467.                         for index := 1 to thecount do
  468.                             if (IUCompString(appl[index].name,
  469.                                             thereply.fname) > 0) then begin
  470.                                 thecount := index;
  471.                                 leave;
  472.                             end;
  473.                         
  474.                         BlockMove(@appl[thecount], @appl[thecount + 1],
  475.                                         GetHandleSize(Handle(thehandle))
  476.                                         - long(@appl[thecount + 1])
  477.                                         + long(thehandle^));
  478.                         
  479.                         BlockMove(@newappl, @appl[thecount], sizeof(tline));
  480.                         
  481.                         ChangedResource(Handle(thehandle));
  482.                         WriteResource(Handle(thehandle));
  483.                     
  484.                     end;
  485.                     HUnlock(Handle(thehandle));
  486.                 
  487.                 end;
  488.                 
  489.                 with newappl do
  490.                     transferappl(name, volume, directory);
  491.             
  492.             end;
  493.             
  494.         end;
  495.         
  496. (*******************************************************************
  497.     
  498.     deleteappl
  499.     ----------
  500.     
  501.     This routine chops an item out of the Transfer menu.
  502.     
  503. *******************************************************************)
  504.  
  505.     procedure deleteappl(thehandle : thandle; theappl : integer);
  506.         
  507.         begin
  508.             
  509.             HLock(Handle(thehandle));
  510.             with thehandle^^ do begin
  511.                 
  512.                 count := count - 1;
  513.                 BlockMove(@appl[theappl + 1], @appl[theappl],
  514.                                 GetHandleSize(Handle(thehandle))
  515.                                 - long(@appl[theappl + 1])
  516.                                 + long(thehandle^));
  517.             
  518.             end;
  519.             HUnlock(Handle(thehandle));
  520.             
  521.             SetHandleSize(Handle(thehandle), 
  522.                             GetHandleSize(Handle(thehandle))
  523.                             - sizeof(tline));
  524.         
  525.         end;
  526.         
  527. (*******************************************************************
  528.     
  529.     dotheok
  530.     -------
  531.     
  532.     Highlight the “ok” button.
  533.     
  534. *******************************************************************)
  535.         
  536.     procedure dotheok(thewindow : WindowPtr; theitem : integer);
  537.             
  538.         var
  539.             thetype            :    integer;
  540.             thehandle        :    Handle;
  541.             therect            :    Rect;
  542.             
  543.         begin
  544.         
  545.             GetDItem(thewindow, ok, thetype, thehandle, therect);
  546.         
  547.             PenSize(3, 3);
  548.             InsetRect(therect, -4, -4);
  549.             FrameRoundRect(therect, 16, 16);
  550.             PenSize(1, 1);
  551.                 
  552.         end;
  553.         
  554. (*******************************************************************
  555.     
  556.     dothelist
  557.     ---------
  558.     
  559.     Draw the dialog's list.
  560.     
  561. *******************************************************************)
  562.         
  563.     procedure dothelist(thewindow : WindowPtr; theitem : integer);
  564.             
  565.         var
  566.             thetype            :    integer;
  567.             thehandle        :    Handle;
  568.             therect            :    Rect;
  569.             
  570.         begin
  571.         
  572.             LUpdate(thewindow^.visRgn, ListHandle(GetWRefCon(thewindow)));
  573.             
  574.             GetDItem(thewindow, theitem, thetype, thehandle, therect);
  575.             InsetRect(therect, - 1, - 1);
  576.             FrameRect(therect);
  577.                 
  578.         end;
  579.         
  580. (*******************************************************************
  581.     
  582.     dotheline
  583.     ---------
  584.     
  585.     Draw a dividing line in the dialog.
  586.     
  587. *******************************************************************)
  588.         
  589.     procedure dotheline(thewindow : WindowPtr; theitem : integer);
  590.             
  591.         var
  592.             thetype            :    integer;
  593.             thehandle        :    Handle;
  594.             therect            :    Rect;
  595.             
  596.         begin
  597.         
  598.             GetDItem(thewindow, theitem, thetype, thehandle, therect);
  599.         
  600.             MoveTo(therect.left, therect.top);
  601.             LineTo(therect.right, therect.top);
  602.                 
  603.         end;
  604.         
  605. (*******************************************************************
  606.     
  607.     editfilter
  608.     ----------
  609.     
  610.     This routine supports the usual keyboard equivalents for dialog
  611.     buttons, as well as “D” for the “Delete” button.  If the mouse
  612.     is clicked in the list, the click is passed to LClick.
  613.     
  614. *******************************************************************)
  615.     
  616.     function editfilter(thedialog : DialogPtr;
  617.                     var theevent : EventRecord;
  618.                     var theitem : integer): logical;
  619.         
  620.         const
  621.             enterkey            =    3;
  622.             returnkey        =    13;
  623.             periodkey        =    46;
  624.         
  625.         var
  626.             thekey            :    integer;
  627.             thepoint            :    Point;
  628.             thetype            :    integer;
  629.             thehandle        :    Handle;
  630.             therect            :    Rect;
  631.         
  632.         begin
  633.             
  634.             editfilter := false;
  635.             
  636.             if theevent.what = keyDown then begin
  637.                 
  638.                 thekey := BitAnd(charCodeMask, theevent.message);
  639.                 if (thekey = enterkey) or (thekey = returnkey) then begin
  640.                     theitem := ok;
  641.                     editfilter := true;
  642.                 end else if thekey = periodkey then begin
  643.                     theitem := cancel;
  644.                     editfilter := true;
  645.                 end else if (thekey = ord('d')) or (thekey = ord('D')) then begin
  646.                     theitem := editdelete;
  647.                     editfilter := true;
  648.                 end;
  649.             
  650.             end else if theevent.what = mouseDown then begin
  651.                 
  652.                 thepoint := theevent.where;
  653.                 
  654.                 GlobalToLocal(thepoint);
  655.                 GetDItem(thedialog, editlist, thetype, thehandle, therect);
  656.                 
  657.                 if PtInRect(thepoint, therect) then begin
  658.                     editfilter := true;
  659.                     if LClick(thepoint, 0, ListHandle(GetWRefCon(thedialog))) then
  660.                         ;
  661.                     theitem := editlist;
  662.                 end;
  663.             
  664.             end;
  665.         
  666.         end;
  667.     
  668. (*******************************************************************
  669.     
  670.     edittransfer
  671.     ------------
  672.     
  673.     This routine puts up a dialog with a list of the applications
  674.     on the menu.  Note that the list uses a custom LDEF.
  675.     
  676.     While the dialog is up, clicking the “Delete” button will delete
  677.     the selected item from the list and the “TRNS” resource.  This
  678.     change can be cancelled, however; if the dialog is dismissed by
  679.     clicking “cancel”, then the resource with the deletions is
  680.     released; the next time it is used, the Resource Manager will
  681.     load the un-deleted version from disk.
  682.     
  683.     If the dialog is dismissed by clicking the “ok” button, then
  684.     the resource is updated.  The menu just shrank, so its dimensions
  685.     must be recalculated with CalcMenuSize.
  686.     
  687. *******************************************************************)
  688.  
  689.     procedure edittransfer;
  690.         
  691.         var
  692.             savedport        :    GrafPtr;
  693.             thedialog        :    DialogPtr;
  694.             therecord        :    DialogRecord;
  695.             thetype            :    integer;
  696.             thehandle        :    Handle;
  697.             therect            :    Rect;
  698.             bounds            :    Rect;
  699.             thepoint            :    Point;
  700.             thethandle        :    thandle;
  701.             thelist            :    ListHandle;
  702.             choice            :    integer;
  703.             
  704.         begin
  705.             
  706.             GetPort(savedport);
  707.             centerdialog('DLOG', editdialog);
  708.             thedialog := GetNewDialog(editdialog, @therecord, pointer(-1));
  709.             SetPort(thedialog);
  710.  
  711.             GetDItem(thedialog, themask, thetype, thehandle, therect);
  712.             thehandle := Handle(@dotheok);
  713.             SetDItem(thedialog, themask, userItem, thehandle, therect);
  714.  
  715.             GetDItem(thedialog, editlist, thetype, thehandle, therect);
  716.             thehandle := Handle(@dothelist);
  717.             SetDItem(thedialog, editlist, userItem, thehandle, therect);
  718.             
  719.             therect.right := therect.right - 15;
  720.             thethandle := thandle(GetResource('TRNS', 1001));
  721.             SetRect(bounds, 0, 0, 1, thethandle^^.count);
  722.             SetPt(thepoint, therect.right - therect.left, 16);
  723.             thelist := LNew(therect, bounds, thepoint, 1001,
  724.                             thedialog, true, false, false, true);
  725.             SetWRefCon(thedialog, long(thelist));
  726.  
  727.             GetDItem(thedialog, editline, thetype, thehandle, therect);
  728.             thehandle := Handle(@dotheline);
  729.             SetDItem(thedialog, editline, userItem, thehandle, therect);
  730.  
  731.             ShowWindow(thedialog);
  732.         
  733.             repeat
  734.                 
  735.                 ModalDialog(@editfilter, choice);
  736.                 
  737.                 if choice = editdelete then begin
  738.                     SetPt(thepoint, 0, 0);
  739.                     if LGetSelect(true, thepoint, thelist) then begin
  740.                         deleteappl(thethandle, thepoint.v + 1);
  741.                         LDelRow(1, thepoint.v, thelist);
  742.                     end;
  743.                 end;
  744.                 
  745.             until (choice = ok) or (choice = cancel);
  746.             
  747.             if choice = cancel then
  748.                 ReleaseResource(Handle(thethandle))
  749.             else begin
  750.                 ChangedResource(Handle(thethandle));
  751.                 WriteResource(Handle(thethandle));
  752.                 CalcMenuSize(TRANSMENU);
  753.             end;
  754.             
  755.             LDispose(thelist);
  756.             CloseDialog(thedialog);
  757.             SetPort(savedport);
  758.             
  759.         end;
  760.         
  761. (*******************************************************************
  762.     
  763.     clicktransfermenu
  764.     -----------------
  765.     
  766.     This routine handles selections from the Transfer menu.  The
  767.     “Transfer...” and “Edit Menu...” commands are performed in
  768.     separate routines above.
  769.     
  770.     Transfers to applications on the menu are done by the “Transfer”
  771.     routine.  If everything works, control never returns; if it does,
  772.     then an error occurred, so delete that item from the menu.
  773.     
  774. *******************************************************************)
  775.  
  776.     procedure clicktransfermenu(theitem : integer);
  777.         
  778.         var
  779.             thehandle        :    thandle;
  780.             thecount            :    integer;
  781.             
  782.         begin
  783.             
  784.             case theitem of
  785.                 transitem    :    newtransfer;
  786.                 edititem        :    edittransfer;
  787.             otherwise
  788.                 
  789.                 thehandle := thandle(GetResource('TRNS', 1001));
  790.                 HLock(Handle(thehandle));
  791.                 with thehandle^^.appl[theitem - 3] do
  792.                     transferappl(name, volume, directory);
  793.                 
  794.                 deleteappl(thehandle, theitem - 3);
  795.                 ChangedResource(Handle(thehandle));
  796.                 WriteResource(Handle(thehandle));
  797.                 CalcMenuSize(TRANSMENU);
  798.             
  799.             end;
  800.             
  801.         end;
  802.         
  803. (******************************************************************)
  804.  
  805.     procedure checkmenu;
  806.             
  807.         begin
  808.             
  809.             if FrontWindow = nil then
  810.                 DisableItem(EDITMENU, 0)
  811.             else
  812.                 EnableItem(EDITMENU, 0);
  813.             
  814.         end;
  815.         
  816. (******************************************************************)
  817.  
  818.     procedure clickinmenu;
  819.             
  820.         var
  821.             choice            :    long;
  822.             
  823.         begin
  824.             
  825.             checkmenu;
  826.             choice := MenuSelect(MAINEVENT.where);
  827.             
  828.             case HiWord(choice) of
  829.                 applenum        :    clickapplemenu(LoWord(choice));
  830.                 filenum        :    doquit(true);
  831.                 editnum        :    if SystemEdit(LoWord(choice) - 1) then;
  832.                 transnum        :    clicktransfermenu(LoWord(choice));
  833.             end;
  834.  
  835.             HiliteMenu(0);
  836.         
  837.         end;
  838.         
  839. (******************************************************************)
  840.     
  841.     procedure aclick;
  842.         
  843.         var
  844.             location            :    integer;
  845.             thewindow        :    WindowPtr;
  846.             
  847.         begin
  848.             
  849.             location := FindWindow(MAINEVENT.where, thewindow);
  850.  
  851.             case location of
  852.                 inDesk        :    SysBeep(1);
  853.                 inMenuBar    :    clickinmenu;
  854.                 inSysWindow    :    SystemClick(MAINEVENT, thewindow);
  855.             end;
  856.         
  857.         end;
  858.         
  859. (******************************************************************)
  860.     
  861.     procedure akey;
  862.         
  863.         var
  864.             charcode            :    integer;
  865.             choice            :    long;
  866.     
  867.         begin
  868.             
  869.             if BitAnd(MAINEVENT.modifiers, cmdKey) <> 0 then begin
  870.     
  871.                 charcode := BitAnd(MAINEVENT.message, charCodeMask);
  872.                 checkmenu;
  873.                 choice := MenuKey(chr(charcode));
  874.                 
  875.                 if choice <> 0 then begin
  876.                 
  877.                     case HiWord(choice) of
  878.                         applenum        :    clickapplemenu(LoWord(choice));
  879.                         filenum        :    doquit(true);
  880.                         editnum        :    if SystemEdit(LoWord(choice) - 1) then;
  881.                         transnum        :    clicktransfermenu(LoWord(choice));
  882.                     end;
  883.                     
  884.                     HiliteMenu(0);
  885.                     
  886.                 end;
  887.                 
  888.             end;
  889.  
  890.         end;
  891.         
  892. (******************************************************************)
  893.     
  894.     procedure mainloop;
  895.         
  896.         var
  897.             dummy                :    logical;
  898.     
  899.         begin
  900.             
  901.             repeat
  902.                 
  903.                 if JEVENT then
  904.                     dummy := waitnextevent(everyEvent, MAINEVENT,
  905.                                     GetCaretTime, nil)
  906.                 else begin
  907.                     SystemTask;
  908.                     dummy := GetNextEvent(everyEvent, MAINEVENT);
  909.                 end;
  910.                 
  911.                 if dummy then begin
  912.                     case MAINEVENT.what of
  913.                         mouseDown        :    aclick;
  914.                         keyDown            :    akey;
  915.                     end;
  916.                 end;
  917.             
  918.             until DONE;
  919.  
  920.         end;
  921.         
  922. (******************************************************************)
  923.     
  924.     begin
  925.         
  926.         initmac;
  927.         setupmenus;
  928.         initglobals;
  929.         
  930.         mainloop;
  931.         
  932.     end.
  933.         
  934. (******************************************************************)
  935.